#ifndef __M_LOOP_H__
#define __M_LOOP_H__
#include "util.hpp" // 通用工具类
#include <vector>
#include <thread>             // 线程支持
#include <mutex>              // 互斥锁
#include <atomic>             // 原子变量
#include <condition_variable> // 条件变量
#include <functional>         // 函数对象
#include "buffer.hpp"         // 缓冲区类

namespace zdflog
{
    /**
     * @brief 异步日志循环器
     * 负责管理后台线程和日志消息队列，实现日志的异步处理
     */
    class AsyncLooper
    {
    public:
        /**
         * @brief 日志处理回调函数类型
         * 接收一个Buffer引用，用于处理异步线程中的日志数据
         */
        using Functor = std::function<void(Buffer &buffer)>;
        using ptr = std::shared_ptr<AsyncLooper>; // 智能指针类型定义

        /**
         * @brief 构造函数
         * @param cb 日志处理回调函数(由外部定义具体输出逻辑)
         */
        AsyncLooper(const Functor &cb) : _running(true),       // 初始化运行状态为true
                                         _looper_callback(cb), // 设置回调函数
                                         _thread(std::thread(&AsyncLooper::worker_loop, this))
        { // 启动工作线程
        }

        /**
         * @brief 析构函数
         * 停止异步循环并释放资源
         */
        ~AsyncLooper() { stop(); }

        /**
         * @brief 停止异步循环器
         * 终止工作线程并等待其退出
         */
        void stop()
        {
            _running = false;       // 原子操作标记停止状态
            _pop_cond.notify_all(); // 唤醒等待的工作线程
            if (_thread.joinable())
            { // 若线程可join，则等待其结束
                _thread.join();
            }
        }

        /**
         * @brief 向异步队列中推送日志消息
         * @param msg 待处理的日志字符串
         */
        void push(const std::string &msg)
        {
            if (_running == false)
            { // 若已停止，则直接返回
                return;
            }
            {
                std::unique_lock<std::mutex> lock(_mutex); // 加锁保护缓冲区操作
                // 等待缓冲区有足够空间写入消息
                // 条件变量等待：当缓冲区可写空间 >= 消息长度时唤醒
                _push_cond.wait(lock, [&]
                                { return _tasks_push.writeAbleSize() >= msg.size(); });
                // 将消息写入推送缓冲区
                _tasks_push.push(msg.c_str(), msg.size());
            }
            _pop_cond.notify_all(); // 唤醒工作线程处理新消息
        }

    private:
        /**
         * @brief 工作线程主循环
         * 后台线程执行的函数，负责从队列中取出消息并调用回调处理
         */
        void worker_loop()
        {
            while (1)
            { // 循环处理消息
                {
                    std::unique_lock<std::mutex> lock(_mutex); // 加锁操作共享资源

                    // 退出条件：已停止运行且推送缓冲区为空
                    if (_running == false && _tasks_push.empty())
                    {
                        return;
                    }

                    // 等待条件：推送缓冲区非空 或 已停止运行
                    // 避免虚假唤醒，使用lambda检查实际条件
                    _pop_cond.wait(lock, [&]
                                   { return !_tasks_push.empty() || !_running; });

                    // 交换推送缓冲区和处理缓冲区，减少锁占用时间
                    // 交换后工作线程可独立处理_pop缓冲区，不影响新消息推送
                    _tasks_push.swap(_tasks_pop);
                }

                _push_cond.notify_all(); // 唤醒可能阻塞的push操作(此时缓冲区已空出)

                // 调用外部传入的回调函数处理消息
                _looper_callback(_tasks_pop);

                // 重置处理缓冲区，准备下次使用
                _tasks_pop.reset();
            }
            return;
        }

    private:
        Functor _looper_callback; // 日志处理回调函数(实际输出逻辑由外部实现)

    private:
        std::mutex _mutex;                  // 互斥锁，保护缓冲区操作的线程安全
        std::atomic<bool> _running;         // 运行状态标记(原子变量，线程安全)
        std::condition_variable _push_cond; // 推送条件变量，用于等待缓冲区空闲空间
        std::condition_variable _pop_cond;  // 处理条件变量，用于通知工作线程处理消息
        Buffer _tasks_push;                 // 推送缓冲区(生产者写入)
        Buffer _tasks_pop;                  // 处理缓冲区(消费者读取)
        std::thread _thread;                // 后台工作线程
    };
}
#endif